package com.kxmall.web.controller.capacity.service.impl;

import com.abc.pay.client.Util;
import com.abc.pay.client.ebus.PaymentResult;
import com.abc.pay.client.ebus.common.EBusMerchantCommonRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.kxmall.capacity.domain.KxCapacityBox;
import com.kxmall.capacity.domain.KxCapacityOrder;
import com.kxmall.capacity.domain.vo.KxCapacityBoxVo;
import com.kxmall.capacity.domain.vo.KxCapacityOrderVo;
import com.kxmall.capacity.domain.vo.KxCapacityVo;
import com.kxmall.capacity.mapper.KxCapacityBoxMapper;
import com.kxmall.capacity.mapper.KxCapacityMapper;
import com.kxmall.capacity.mapper.KxCapacityOrderMapper;
import com.kxmall.common.constant.CacheConstants;
import com.kxmall.common.utils.*;
import com.kxmall.common.utils.redis.RedisUtils;
import com.kxmall.web.controller.capacity.service.IKxCapacityService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.Duration;
import java.util.*;

@Slf4j
@Service
@RequiredArgsConstructor
public class KxCapacityService implements IKxCapacityService {

    private final KxCapacityMapper capacityMapper;

    private final KxCapacityBoxMapper capacityBoxMapper;

    private final KxCapacityOrderMapper capacityOrderMapper;

    private final String loginURL = "https://middle.office.xingshentech.com/api/sys/singleLogin?userName=qdqTest&password=qdqTest";

    private final String openURL = "https://middle.office.xingshentech.com/api/task/interface/cabinetMissionOpen";

    private final String getURL = "https://middle.office.xingshentech.com/api/task/interface/capacityResourceBoxStatusById?capacityResourceId=";

    private final String shareTokenURL = "https://wx.abchina.com/webank/main-view/openTagForNBSes?id=%2FAOmtaFJ%2FYM%3D&dynamicData=";

    private final String merchantNotifyURL =  "https://mall.mosunshine.com/capacity/abc_pay_notify";

    @Override
    public KxCapacityVo getCapacityBoxStatus(String capacityId) {
        log.info("getCapacityBoxStatus capacityId={}", capacityId);
        String token = RedisUtils.getCacheObject(CacheConstants.CAPACITY_LOGIN_TOKEN_KEY);
        if(StringUtils.isEmpty(token)){
            token = getCapacityLoginToken();
        }
        Map<String, String> headers = new HashMap<>();
        if(StringUtils.isNotEmpty(token)) {
            headers.put("token", token);
        }
        log.info("getCapacityBoxStatus capacityId={} token={}", capacityId, token);
        String response = HttpUtils.get(getURL+capacityId,null, headers);
        log.info(response);
        Map<String,Object> rpMap = JSON.parseObject(response, HashMap.class);
        if ("0".equals(""+rpMap.get("code"))){
            KxCapacityVo kxCapacityVo = JSON.parseObject(""+rpMap.get("data"), KxCapacityVo.class);
            List<KxCapacityBoxVo> kxCapacityBoxVOList = kxCapacityVo.getBoxStatusInfoVOList();
            if(CollectionUtils.isNotEmpty(kxCapacityBoxVOList)){
                for(KxCapacityBoxVo kxCapacityBoxVo : kxCapacityBoxVOList){
                    KxCapacityBox capacityBox = new KxCapacityBox();
                    capacityBox.setCapacityId(capacityId);
                    capacityBox.setBoxIndex(kxCapacityBoxVo.getBoxIndex());
                    capacityBox.setBoxStatus(kxCapacityBoxVo.getBoxStatus());
                    capacityBox.setState(kxCapacityBoxVo.getState());
                    capacityBoxMapper.insertOrUpdate(capacityBox);
                }
            }
            log.info("getCapacityBoxStatus kxCapacityVo={}",JSONObject.toJSONString(kxCapacityVo));
            return kxCapacityVo;
        }
        if ("401".equals(""+rpMap.get("code"))){
            getCapacityLoginToken();
            KxCapacityVo kxCapacityVo = getCapacityBoxStatus(capacityId);
            log.info("getCapacityBoxStatus kxCapacityVo={}", JSONObject.toJSONString(kxCapacityVo));
            return kxCapacityVo;
        }
        KxCapacityVo kxCapacityVo = new KxCapacityVo();
        kxCapacityVo.setBoxNum(24);
        List<KxCapacityBoxVo> boxStatusInfoVOList = new ArrayList<>();
        KxCapacityBoxVo kxCapacityBoxVo1 = new KxCapacityBoxVo();
        kxCapacityBoxVo1.setBoxIndex(1);
        kxCapacityBoxVo1.setBoxStatus(0);
        kxCapacityBoxVo1.setState("Closed");
        boxStatusInfoVOList.add(kxCapacityBoxVo1);
        KxCapacityBoxVo kxCapacityBoxVo2 = new KxCapacityBoxVo();
        kxCapacityBoxVo2.setBoxIndex(2);
        kxCapacityBoxVo2.setBoxStatus(1);
        kxCapacityBoxVo2.setState("Opened");
        boxStatusInfoVOList.add(kxCapacityBoxVo2);
        for(int i=3; i<25; i++){
            KxCapacityBoxVo kxCapacityBoxVo = new KxCapacityBoxVo();
            kxCapacityBoxVo.setBoxIndex(i);
            kxCapacityBoxVo.setBoxStatus(-1);
            kxCapacityBoxVo.setState("Offline");
            boxStatusInfoVOList.add(kxCapacityBoxVo);
        }
        kxCapacityVo.setBoxStatusInfoVOList(boxStatusInfoVOList);
        log.info("getCapacityBoxStatus kxCapacityVo={}", JSONObject.toJSONString(kxCapacityVo));
        return kxCapacityVo;
    }

    @Override
    public PageData createCapacityBoxOrder(String capacityId, Integer boxIndex) {
        log.info("createCapacityBoxOrder capacityId={} boxIndex={}", capacityId, boxIndex);
        PageData ack = new PageData();
        String orderNo = OrderUtil.getOrderIdByUUId();
        try {
            EBusMerchantCommonRequest eBusMerchantCommonRequest = new EBusMerchantCommonRequest();
            eBusMerchantCommonRequest.dicRequest.put("TrxType", "PayReq");
            LinkedHashMap dicOrder = new LinkedHashMap();
            dicOrder.put("PayTypeID", "ImmediatePay");//设定交易类型
            dicOrder.put("OrderDate", DateUtils.getDay1());//设定订单日期 （必要信息 - YYYY/MM/DD）
            dicOrder.put("OrderTime", DateUtils.getTime1());//设定订单时间 （必要信息 - HH:MM:SS）
            dicOrder.put("orderTimeoutDate", DateUtils.getTimeStampStr(System.currentTimeMillis()+1800000));
            dicOrder.put("OrderNo", orderNo);//设定订单编号 （必要信息）
            dicOrder.put("CurrencyCode", "156");//设定交易币种
            dicOrder.put("OrderAmount", "0.01");//设定交易金额 1.00
            dicOrder.put("Fee", "0.00");
            dicOrder.put("AccountNo", "");
            dicOrder.put("OrderDesc", "摩创");
            dicOrder.put("ReceiverAddress", "苏州");
            dicOrder.put("InstallmentMark", "0");
            dicOrder.put("ExpiredDate","30");
            dicOrder.put("CommodityType", "0202");//设置商品种类
            dicOrder.put("BuyIP", "127.0.0.1");//IP
            dicOrder.put("OrderItems", "[{\"ProductName\":\"摩创\"}]");//订单详情循环域，用来登记和展示
            eBusMerchantCommonRequest.dicRequest.put("Order", dicOrder);
            eBusMerchantCommonRequest.dicRequest.put("PaymentType", "Z");//设定支付账户类型 H5数币的话送Z
            eBusMerchantCommonRequest.dicRequest.put("PaymentLinkType", "2");//设定支付交易渠道 2 短信验证码支付

            eBusMerchantCommonRequest.dicRequest.put("NotifyType", "1");//设定通知方式
            eBusMerchantCommonRequest.dicRequest.put("ResultNotifyURL", merchantNotifyURL);//设定通知URL地址
            eBusMerchantCommonRequest.dicRequest.put("MerchantRemarks", "");//设定附言//设备终端号
            eBusMerchantCommonRequest.dicRequest.put("IsBreakAccount", "0");//
            eBusMerchantCommonRequest.dicRequest.put("SplitAccTemplate", "");//
            eBusMerchantCommonRequest.dicRequest.put("ReceiveAccount", "");//
            eBusMerchantCommonRequest.dicRequest.put("ReceiveAccName", "");//
            log.info("AppServiceImpl createOrder dicRequest:{}", JSONObject.toJSONString(eBusMerchantCommonRequest.dicRequest));
            com.abc.pay.client.JSON responseJson = eBusMerchantCommonRequest.postRequest();
            if (responseJson == null) {
                ack.put("respcode", Const.RESP_ERROR_PAY_CHANNEL_NOT_OPENED);
                ack.put("respdesc", "农行支付生成订单失败");
                return ack;
            }
            log.info("AppServiceImpl createOrder responseJson:{}", responseJson);
            String ReturnCode = responseJson.GetKeyValue("ReturnCode");
            String ErrorMessage = responseJson.GetKeyValue("ErrorMessage");
            ack.put("respcode", ReturnCode);
            ack.put("respdesc", ErrorMessage);
            if (ReturnCode.equals("0000")) {
                //5、请求提交成功，返回结果信息
                String OrderNo = responseJson.GetKeyValue("OrderNo");
                String PaymentURL = responseJson.GetKeyValue("PaymentURL");
                String OrderAmount = responseJson.GetKeyValue("OrderAmount");
                ack.put("orderId", OrderNo);
                ack.put("URL", PaymentURL);
                ack.put("amount", OrderAmount);
                String tokenID = PaymentURL.substring(PaymentURL.indexOf("TOKEN")+6).toLowerCase();
                ack.put("tokenID", tokenID);
                log.info("tokenID={}",tokenID);

                String dynamicData = Util.encryptCBCMode("tokenID=" + tokenID, "bankabc1", "abchina1");
                log.info("dynamicData={}",dynamicData);
                String dynamicData1 = URLEncoder.encode(dynamicData,"UTF-8");
                log.info(dynamicData1);
                log.info("dynamicData1={}",dynamicData1);
                String ShareTokenURL = shareTokenURL + dynamicData1;
                ack.put("ShareTokenURL", ShareTokenURL);
                log.info("ShareTokenURL={}",ShareTokenURL);
                BigDecimal amount = new BigDecimal(0.01);
                KxCapacityOrder capacityOrder = new KxCapacityOrder();
                capacityOrder.setOrderNo(orderNo);
                capacityOrder.setCapacityId(capacityId);
                capacityOrder.setBoxIndex(boxIndex);
                capacityOrder.setPrice(amount);
                capacityOrder.setNumber(1);
                capacityOrder.setAmount(amount);
                capacityOrder.setCreateBy("admin");
                capacityOrder.setUpdateBy("admin");
                capacityOrder.setCreateTime(new Date());
                capacityOrder.setUpdateTime(new Date());
                capacityOrderMapper.insert(capacityOrder);
            }
        }catch (Exception ex){
            ex.printStackTrace();
            log.error(Util.getExceptionString(ex));
            ack.put("respcode", Const.RESP_ERROR_PAY_CHANNEL_NOT_OPENED);
            ack.put("respdesc", "农行支付生成订单失败");
        }
        log.info("createCapacityBoxOrder capacityId={} ack={}", capacityId, ack);
        return ack;
    }

    @Override
    public Boolean openCapacityBox(String capacityId, Integer boxIndex) {
        log.info("openCapacityBox capacityId={} boxIndex={}", capacityId, boxIndex);
        Map<String, String> params = new HashMap<>();
        params.put("capacityResourceId", capacityId);
        params.put("boxIndex", boxIndex+"");

        String token = RedisUtils.getCacheObject(CacheConstants.CAPACITY_LOGIN_TOKEN_KEY);
        if(StringUtils.isEmpty(token)){
            token = getCapacityLoginToken();
        }
        Map<String, String> headers = new HashMap<>();
        if(StringUtils.isNotEmpty(token)) {
            headers.put("token", token);
        }
        log.info("openCapacityBox capacityId={} boxIndex={} token={}", capacityId, boxIndex, token);
        String response = HttpUtils.post(openURL, params, headers);
        log.info(response);
        Map<String,Object> rpMap= JSON.parseObject(response, HashMap.class);
        if ("0".equals(""+rpMap.get("code"))){
            Boolean status = (Boolean) rpMap.get("status");
            return status;
        }
        return false;
    }

    public String appAbcPayNotify(String msg) {
        log.info("AppServiceImpl appAbcPayNotify msg:{}", msg);
        PageData ack = new PageData();
        try {
            PaymentResult tResult = new PaymentResult(msg);
            ack.put("respcode",tResult.getReturnCode());
            ack.put("respdesc",tResult.getErrorMessage());
            if (tResult.isSuccess()) {
                ack.put("MerchantID",tResult.getValue("MerchantID"));
                ack.put("TrxType",tResult.getValue("TrxType"));
                ack.put("OrderNo",tResult.getValue("OrderNo"));
                ack.put("Amount",tResult.getValue("Amount"));
                ack.put("BatchNo",tResult.getValue("BatchNo"));
                ack.put("VoucherNo",tResult.getValue("VoucherNo"));
                ack.put("HostDate",tResult.getValue("HostDate"));
                ack.put("HostTime",tResult.getValue("HostTime"));
                ack.put("PayType",tResult.getValue("PayType"));
                ack.put("NotifyType",tResult.getValue("NotifyType"));
                ack.put("iRspRef",tResult.getValue("iRspRef"));
                ack.put("AcqFee",tResult.getValue("AcqFee"));
                ack.put("AccDate",tResult.getValue("AccDate"));
                ack.put("IssFee",tResult.getValue("IssFee"));
                String orderNo = tResult.getValue("OrderNo");
                if(StringUtils.isNotEmpty(orderNo)) {
                    KxCapacityOrderVo capacityOrderVo = capacityOrderMapper.selectVoOne(
                            new LambdaQueryWrapper<KxCapacityOrder>().eq(KxCapacityOrder::getOrderNo, orderNo));
                    if (capacityOrderVo != null) {
                        openCapacityBox(capacityOrderVo.getCapacityId(), capacityOrderVo.getBoxIndex());
                        return capacityOrderVo.getCapacityId();
                    }
                }
            }
        } catch (Exception e){
            e.printStackTrace();
            log.error(Util.getExceptionString(e));
        }
        log.info("AppServiceImpl appAbcPayNotify ack:{}", ack);
        return null;
    }

    public String getCapacityLoginToken(){
        String response = HttpUtils.get(loginURL);
        Map<String,Object> rpMap= JSON.parseObject(response, HashMap.class);
        if ("0".equals(""+rpMap.get("code"))){
            String data = ""+rpMap.get("data");
            Map<String,Object> rpMap1= JSON.parseObject(data, HashMap.class);
            String token = ""+rpMap1.get("token");
            Duration duration = Duration.ofDays(1);
            RedisUtils.setCacheObject(CacheConstants.CAPACITY_LOGIN_TOKEN_KEY, token, duration);
            return token;
        }
        return "";
    }
}
